# Compiler
CXX?=g++
CPPFLAGS=-c -ggdb -ansi -Iinclude/ -Ibuild/ -Imodules/ -I.
CPPFLAGS2=-ggdb -ansi
CPPFLAGS3=-c -ggdb -ansi -Iinclude/ -Ibuild/ -I.
# Linker
LD=g++
LFLAGS=-ggdb -O2
# Bison, re2c
BISON=bison
RE2C=re2c
# Build dir
BUILDDIR=build/
# Core source dir
SRCDIR=core/
# Testrunner dir
EXTRADIR=extra/

OBJECTS=$(BUILDDIR)parser.o $(BUILDDIR)scanner.o $(BUILDDIR)driver.o $(BUILDDIR)compiler.o $(BUILDDIR)vm.o \
		$(BUILDDIR)main.o $(BUILDDIR)types.o $(BUILDDIR)numeric.o $(BUILDDIR)str.o \
		$(BUILDDIR)bool.o $(BUILDDIR)int.o $(BUILDDIR)double.o $(BUILDDIR)object.o $(BUILDDIR)API.o \
		$(BUILDDIR)opcodes.o $(BUILDDIR)vector.o $(BUILDDIR)map.o $(BUILDDIR)internal.o \
		$(BUILDDIR)module.o $(BUILDDIR)core.o $(BUILDDIR)gc.o

todo: $(OBJECTS)
	$(LD) $(LFLAGS) -o todo $(BUILDDIR)*.o

all: todo test

$(BUILDDIR)driver.o: $(SRCDIR)driver.cpp $(BUILDDIR)parser.o
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)driver.o $(SRCDIR)driver.cpp

$(BUILDDIR)types.o: $(SRCDIR)types.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)types.o $(SRCDIR)types.cpp
	
$(BUILDDIR)str.o: $(SRCDIR)str.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)str.o $(SRCDIR)str.cpp
	
$(BUILDDIR)bool.o: $(SRCDIR)bool.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)bool.o $(SRCDIR)bool.cpp

$(BUILDDIR)int.o: $(SRCDIR)int.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)int.o $(SRCDIR)int.cpp
	
$(BUILDDIR)double.o: $(SRCDIR)double.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)double.o $(SRCDIR)double.cpp
	
$(BUILDDIR)numeric.o: $(SRCDIR)numeric.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)numeric.o $(SRCDIR)numeric.cpp

$(BUILDDIR)object.o: $(SRCDIR)object.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)object.o $(SRCDIR)object.cpp

$(BUILDDIR)vector.o: $(SRCDIR)vector.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)vector.o $(SRCDIR)vector.cpp
	
$(BUILDDIR)map.o: $(SRCDIR)map.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)map.o $(SRCDIR)map.cpp
	
$(BUILDDIR)compiler.o: $(SRCDIR)compiler.cpp $(BUILDDIR)parser.o
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)compiler.o $(SRCDIR)compiler.cpp

$(BUILDDIR)main.o: $(SRCDIR)main.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)main.o $(SRCDIR)main.cpp

$(BUILDDIR)API.o: $(SRCDIR)API.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)API.o $(SRCDIR)API.cpp
	
$(BUILDDIR)gc.o: $(SRCDIR)gc.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)gc.o $(SRCDIR)gc.cpp
	
$(BUILDDIR)internal.o: $(SRCDIR)internal.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)internal.o $(SRCDIR)internal.cpp
	
$(BUILDDIR)module.o: modules/module.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)module.o modules/module.cpp

$(BUILDDIR)core.o: $(BUILDDIR)module.o modules/std/core.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)core.o modules/std/core.cpp

$(BUILDDIR)vm.o: $(SRCDIR)vm.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)vm.o $(SRCDIR)vm.cpp
	
$(BUILDDIR)opcodes.o: $(SRCDIR)opcodes.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)opcodes.o $(SRCDIR)opcodes.cpp

$(BUILDDIR)parser.cpp: $(SRCDIR)parser.y
	$(BISON) -d -o$(BUILDDIR)parser.cpp $(SRCDIR)parser.y
	
$(BUILDDIR)parser.o: $(BUILDDIR)parser.cpp
	$(CXX) $(CPPFLAGS3) -o $(BUILDDIR)parser.o $(BUILDDIR)parser.cpp
 
$(BUILDDIR)scanner.cpp: $(SRCDIR)scanner.re $(BUILDDIR)parser.o
	$(RE2C) --case-insensitive -b -c -o $(BUILDDIR)scanner.cpp $(SRCDIR)scanner.re

$(BUILDDIR)scanner.o: $(BUILDDIR)scanner.cpp
	$(CXX) $(CPPFLAGS) -o $(BUILDDIR)scanner.o $(BUILDDIR)scanner.cpp

test: $(EXTRADIR)testrunner.cpp
	$(CXX) $(CPPFLAGS2) -o $(EXTRADIR)testrunner $(EXTRADIR)testrunner.cpp -lpcrecpp
	
tests: todo test
	./extra/testrunner tests/

clean:
	rm -f todo $(EXTRADIR)testrunner $(BUILDDIR)*

clean-tests:
	rm -rf tests/*.log tests/*.mem
	
clean-all: clean clean-tests
